#include "DoubleLinkList.h"
#include "TwoDArray.h"
#include "../aoi/Scene.h"
template<typename T>
DoubleLinkList<T>::DoubleLinkList(){
    m_pHead = NULL;
    m_pTail = NULL;
    m_nNodeNum = 0;
}

template<typename T>
DoubleLinkList<T>::~DoubleLinkList(){
    m_pHead = NULL;
    m_pTail = NULL;
    m_nNodeNum = 0;
}

template<typename T>
inline bool DoubleLinkList<T>::Add(T* pNode){
    assert(!pNode->pNext && !pNode->pPrev);
    if (pNode->GetScene() == NULL){
        assert(0);
    }
#ifdef DEBUG
    Checker();
#endif

    if (!pNode){
        return false;
    }

    if (m_pTail == NULL){
        m_pHead = pNode;
        m_pTail = pNode;
        pNode->pPrev = NULL;
        pNode->pNext = NULL;
    }else{
        m_pTail->pNext = pNode;
        pNode->pPrev = m_pTail;
        pNode->pNext = NULL;
        m_pTail = pNode;
    }

    ++m_nNodeNum;

#ifdef DEBUG
    Checker();
#endif

    return true;
}

template<typename T>
inline bool DoubleLinkList<T>::Del(T* pNode){
#ifdef DEBUG
    CheckBeforeDel(pNode);
    Checker();
#endif

    if (!pNode )
        return false;

    if (pNode == m_pHead && pNode == m_pTail){
        m_pHead = NULL;
        m_pTail = NULL;
        pNode->pPrev = NULL;
        pNode->pNext = NULL;
        --m_nNodeNum;
        return true;
    }

    if (pNode == m_pHead){
        m_pHead = pNode->pNext;
        m_pHead->pPrev = NULL;
        pNode->pNext = NULL;
        --m_nNodeNum;
        return true;
    }

    if (pNode == m_pTail){
        m_pTail = pNode->pPrev;
        m_pTail->pNext = NULL;
        pNode->pPrev = NULL;
        --m_nNodeNum;
        return true;
    }

    if (pNode->pPrev){
        pNode->pPrev->pNext = pNode->pNext;
    }

    if (pNode->pNext){
        pNode->pNext->pPrev = pNode->pPrev;
    }

    --m_nNodeNum;
    pNode->pNext = 0;
    pNode->pPrev = 0;
    return true;
}

template<typename T>
inline T* DoubleLinkList<T>::GetHead(){
    return m_pHead;
}

template<typename T>
inline short DoubleLinkList<T>::GetLength(){
    return m_nNodeNum;
}

template<typename T>
bool DoubleLinkList<T>::Checker(){
    int cnt = 0;
    for (T *pNode = m_pHead; pNode; pNode = pNode->pNext)
    {
        TwoDIndex oIndex;
        Scene *pScene = pNode->GetScene();
        pScene->GetZoneIndex(pNode->GetPosition(), &oIndex);
        Zone *pZone = pScene->m_pZoneTable->Get(&oIndex);
        assert(&pZone->ObjList == this);
        ++cnt;
        assert(cnt <= m_nNodeNum);
    }
    assert(cnt == m_nNodeNum);
    return true;
}

template<typename T>
bool DoubleLinkList<T>::CheckBeforeDel(T *pNode)
{
    TwoDIndex oIndex;
    Scene *pScene = pNode->GetScene();
    pScene->GetZoneIndex(pNode->GetPosition(), &oIndex);
    Zone *pZone = pScene->m_pZoneTable->Get(&oIndex);
    assert(&pZone->ObjList == this);
    return true;
}
